﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BZV.Core.Net;

namespace BZV.Foundation.Business
{
    public class Analyzer
    {
        // 数据池
        private List<Lottery> m_lotterys;

#region 组态
        // 20组六到20组六的二阶
        public int[,] CombinSixToSix;
        // 20组六到20组六的三阶
        public int[, ,] CombinSixToSix3;
        // 20组三到20组三二阶
        public int[,] CombinThreeToThree;
        // 20组三到20组三三阶
        public int[, ,] CombinThreeToThree3;
        // 组三到组六个数
        public int[,] CombinThreeToSix;
        // 组六到组三
        public int[,] CombinSixToThree;
#endregion

#region 个数统计
        // 10个数到10个数的二阶
        public List<int[,]> TenToTen;

        // 10个数到10个数的三阶
        public List<int[, ,]> TenToTen3;

        // 20个数到20个数的二阶
        public List<int[,]> TwoToTwo;

        // 20个数到20个数的三阶
        public List<int[, ,]> TwoToTwo3;

        // 相同的数子个数到不出现的次数
        public List<int[,]> SameToUnSame;
#endregion

        public Analyzer()
        {
            string strCurPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
            // 20组六到20组六的二阶
            CombinSixToSix = (int[,])SerializeHelper.BinaryToDeserialize(strCurPath + "\\7.dat");
            // 20组六到20组六的三阶
            CombinSixToSix3 = (int[,,])SerializeHelper.BinaryToDeserialize(strCurPath + "\\6.dat"); ;
            // 20组三到20组三二阶
            CombinThreeToThree = (int[,])SerializeHelper.BinaryToDeserialize(strCurPath + "\\11.dat");
            // 20组三到20组三三阶
            CombinThreeToThree3 = (int[,,])SerializeHelper.BinaryToDeserialize(strCurPath + "\\10.dat"); ;
            // 组三到组六个数
            CombinThreeToSix = (int[,])SerializeHelper.BinaryToDeserialize(strCurPath + "\\8.dat");
            // 组六到组三
            CombinSixToThree = (int[,])SerializeHelper.BinaryToDeserialize(strCurPath + "\\9.dat");


            // 10个数到10个数的二阶
            TenToTen = (List<int[,]>)SerializeHelper.BinaryToDeserialize(strCurPath + "\\3.dat");

            // 10个数到10个数的三阶
            TenToTen3 = (List<int[,,]>)SerializeHelper.BinaryToDeserialize(strCurPath + "\\4.dat");

            // 20个数到20个数的二阶
            TwoToTwo = (List<int[,]>)SerializeHelper.BinaryToDeserialize(strCurPath + "\\2.dat");

            // 20个数到20个数的三阶
            TwoToTwo3 = (List<int[,,]>)SerializeHelper.BinaryToDeserialize(strCurPath + "\\1.dat");

            // 相同的数子个数到不出现的次数
            SameToUnSame = (List<int[,]>)SerializeHelper.BinaryToDeserialize(strCurPath + "\\5.dat");
        }

        /// <summary>
        /// 设置数据池
        /// </summary>
        /// <param name="dataPool"></param>
        public void SetData(List<Lottery> lotterys)
        {
            m_lotterys = lotterys;
        }

        /// <summary>
        /// 计算结果参数
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="nLen"></param>
        /// <returns></returns>
        public ResultParam CalculateReusltParam(int nIndex, int nLen)
        {
            // 结果参数
            ResultParam resultParam = new ResultParam();

            // 循环计算
            for (int i = nIndex + nLen; i > nIndex; i--)
            {
                Lottery lottery = m_lotterys[i];

                resultParam.Count++;
                // 计算组态
                resultParam.CombinationCount[lottery.Param.comState]++;

                // 获取单双和大小
                for (int k = 0; k < lottery.Param.attrStates.Count; k++)
                {
                    resultParam.AttributesCount[k][lottery.Param.attrStates[k]]++;

                    resultParam.SizesCount[k][lottery.Param.sizeStates[k]]++;
                }

                // 后三位中，每位中各个数字出现的次数
                string strCode = lottery.Code;
                for (int j = 2; j < strCode.Length; j++)
                {
                    // 得到单个的数值
                    string strOne = strCode[j].ToString();
                    int num = Convert.ToInt32(strOne);
                    resultParam.LastThreePerCount[j - 2, num]++;

                    // 三个合起来总共一起的数字个数
                    resultParam.LastThreeAllCount[num]++;
                }
            }

            resultParam.LastThreeAllCount = Sort(resultParam.LastThreeAllCount);

            return resultParam;
        }

#region 组态统计分析
        /// <summary>
        /// 获取当前位置以前nIndex以前的基本参数（包含当前位置）
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="lenght"></param>
        /// <returns></returns>
        public UintParam GetUintIndex(int nIndex, int lenght = 20)
        {
            UintParam param = new UintParam();
            int nSix = 0;
            int nThree = 0;
            int nAll = 0;
            for (int i = nIndex + lenght - 1; i >= nIndex; i--)
            {
                // 获取彩票
                Lottery lottery = m_lotterys[i];
                switch (lottery.Param.comState)
                {
                    case CombinationState.EN_COM_THREE:             // 组三
                        {
                            nThree++;
                            break;
                        }
                    case CombinationState.EN_COM_SIX:               // 组六
                        {
                            nSix++;
                            break;
                        }

                    case CombinationState.EN_COM_ALL:               // 豹子
                        {
                            nAll++;
                            break;
                        }
                }
            }

            // 添加个数
            param.CombinationCount[CombinationState.EN_COM_THREE] = nThree;
            param.CombinationCount[CombinationState.EN_COM_SIX] = nSix;
            param.CombinationCount[CombinationState.EN_COM_ALL] = nAll;

            // 组三的分布
            double dTotal = (double)(nThree + nAll + nSix);
            double dPercent = (nThree + nAll) / (double)(nThree + nAll + nSix);
            param.ThreeDis = GetThreDis(dPercent);

            // 百分比
            param.CombinationPercent[CombinationState.EN_COM_THREE] = nThree / dTotal;
            param.CombinationPercent[CombinationState.EN_COM_SIX] = nSix / dTotal;
            param.CombinationPercent[CombinationState.EN_COM_ALL] = nAll / dTotal;

            return param;
        }

        /// <summary>
        /// 计算组态转移矩阵， 很耗时.当前20个中组六个个数到下个20个中组六的个数
        /// </summary>
        /// <returns></returns>
        public int[,] CalculateCombinSixToSixMatrix()
        {
            int[,] CombinMatrix = new int[21, 21];                 // 转移矩阵
            for (int i = 0; i < 21; i++)
            {
                for (int j = 0; j < 21; j++)
                {
                    for (int k = 20000; k > 20; k--)
                    {
                        UintParam param = GetUintIndex(k, 20);
                        UintParam nextParam = GetUintIndex(k - 20, 20);
                        int nSix = param.CombinationCount[CombinationState.EN_COM_SIX];
                        int nNext = nextParam.CombinationCount[CombinationState.EN_COM_SIX];

                        if (nSix == i && nNext == j)
                        {
                            CombinMatrix[i, j]++;
                        }

                    }
                }

            }

            return CombinMatrix;
        }

        /// <summary>
        /// 计算组态转移矩阵， 很耗时.当前20个中组六个个数到下个20个中组六的个数
        /// </summary>
        /// <returns></returns>
        public int[,,] CalculateCombinSixToSixMatrix3()
        {
            int[,,] CombinMatrix = new int[21, 21, 21];                 // 转移矩阵
            for (int i = 0; i < 21; i++)
            {
                for (int j = 0; j < 21; j++)
                {
                    for (int n = 0; n < 21; n++)
                    {
                        for (int k = 20000; k > 20 * 2; k--)
                        {
                            UintParam param = GetUintIndex(k, 20);
                            UintParam nextParam = GetUintIndex(k - 20, 20);
                            UintParam next2Param = GetUintIndex(k - 20 * 2, 20);
                            int nSix = param.CombinationCount[CombinationState.EN_COM_SIX];
                            int nNext = nextParam.CombinationCount[CombinationState.EN_COM_SIX];
                            int n2Next = next2Param.CombinationCount[CombinationState.EN_COM_SIX];

                            if (nSix == i && nNext == j && n2Next == n)
                            {
                                CombinMatrix[i, j, n]++;
                            }

                        }
                    }
                }

            }

            return CombinMatrix;
        }

        /// <summary>
        /// 计算组态转移矩阵， 很耗时.当前20个中组三个个数到下个20个中组三的个数
        /// </summary>
        /// <returns></returns>
        public int[,] CalculateCombinThreeToThreeMatrix()
        {
            int[,] CombinMatrix = new int[21, 21];                 // 转移矩阵
            for (int i = 0; i < 21; i++)
            {
                for (int j = 0; j < 21; j++)
                {
                    for (int k = 20000; k > 20; k--)
                    {
                        UintParam param = GetUintIndex(k, 20);
                        UintParam nextParam = GetUintIndex(k - 20, 20);
                        int nSix = 20 - param.CombinationCount[CombinationState.EN_COM_SIX];
                        int nNext = 20 - nextParam.CombinationCount[CombinationState.EN_COM_SIX];

                        if (nSix == i && nNext == j)
                        {
                             CombinMatrix[i, j]++;
                        }

                    }
                }

            }

            return CombinMatrix;
        }

        /// <summary>
        /// 计算组态转移矩阵， 很耗时.当前20个中组三个个数到下个20个中组三的个数 三阶
        /// </summary>
        /// <returns></returns>
        public int[,,] CalculateCombinThreeToThreeMatrix3()
        {
            int[,,] CombinMatrix = new int[21, 21, 21];                 // 转移矩阵
            for (int i = 0; i < 21; i++)
            {
                for (int j = 0; j < 21; j++)
                {
                    for (int n = 0; n < 21; n++)
                    {
                        for (int k = 20000; k > 20 * 2; k--)
                        {
                            UintParam param = GetUintIndex(k, 20);
                            UintParam nextParam = GetUintIndex(k - 20, 20);
                            UintParam next2Param = GetUintIndex(k - 20 * 2, 20);
                            int nSix = 20 - param.CombinationCount[CombinationState.EN_COM_SIX];
                            int nNext = 20 - nextParam.CombinationCount[CombinationState.EN_COM_SIX];
                            int n2Next = next2Param.CombinationCount[CombinationState.EN_COM_SIX];

                            if (nSix == i && nNext == j && n2Next == n)
                            {
                                CombinMatrix[i, j, n]++;
                            }

                        }
                    }
                }

            }

            return CombinMatrix;
        }

        /// <summary>
        /// 从连续组三个数到组六个数
        /// </summary>
        /// <returns></returns>
        public int[,] CalculateCombinThreeToSixMatrix()
        {
            int[,] CombinMatrix = new int[10, 30];                 // 转移矩阵
            bool bIsContinueThree = false;
            int nContiuneThreeCount = 0;
            int nContiuneSixCount = 0;
            for (int k = 20000; k >0; k--)
            {
                Lottery lot = m_lotterys[k];
                if (lot.Issue == "141113031")
                {
                    int d = 0;
                }
                if (lot.Param.comState != CombinationState.EN_COM_SIX)
                {
                    if (!bIsContinueThree)              // 上一次不是组三
                    {
                        CombinMatrix[nContiuneThreeCount, nContiuneSixCount]++;
                        nContiuneThreeCount = 0;
                        nContiuneSixCount = 0;
                    }
                    bIsContinueThree = true;
                    nContiuneThreeCount++;
                }
                else
                {
                    bIsContinueThree = false;
                    nContiuneSixCount++;
                }
            }

            return CombinMatrix;
        }

        /// <summary>
        /// 从连续组六个数到组三个数
        /// </summary>
        /// <returns></returns>
        public int[,] CalculateCombinSixToThreeMatrix()
        {
            int[,] CombinMatrix = new int[30, 10];                 // 转移矩阵
            bool bIsContinueSix = false;
            int nContiuneThreeCount = 0;
            int nContiuneSixCount = 0;
            for (int k = 20000; k > 0; k--)
            {
                Lottery lot = m_lotterys[k];
                if (lot.Param.comState == CombinationState.EN_COM_SIX)
                {
                    if (!bIsContinueSix)              // 上一次不是组六
                    {
                        CombinMatrix[nContiuneSixCount, nContiuneThreeCount]++;
                        nContiuneThreeCount = 0;
                        nContiuneSixCount = 0;
                    }
                    bIsContinueSix = true;
                    nContiuneSixCount++;
                }
                else
                {
                    bIsContinueSix = false;
                    nContiuneThreeCount++;
                }
            }

            return CombinMatrix;
        }

        /// <summary>
        /// 在20里面，组六大于19的20组合中。计算以前80的基本参数
        /// </summary>
        /// <returns></returns>
        public List<UintParam> CalculateBestBefore80()
        {
            List<UintParam> results = new List<UintParam>();
            for (int k = 20000; k > 0; k--)
            {
                // 个数不够
                if (k >= 20000 - 101)
                {
                    continue;
                }
                else if(k <= 20)
                {
                    break;
                }

                // 开始计算
                UintParam next20Param = GetUintIndex(k, 20);
                if (next20Param.CombinationCount[CombinationState.EN_COM_SIX] >= 20)
                {
                    UintParam next80Param = GetUintIndex(k - 20, 80);
                    results.Add(next80Param);
                    k -= 19;
                }

            }

            return results;
        }
#endregion

#region 数字统计分析

        /// <summary>
        /// 获取当前位置以前nIndex以前的基本参数（包含当前位置）
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="lenght"></param>
        /// <returns></returns>
        public int [] GetNumCount(int nIndex, int lenght = 20)
        {
            int[] param = new int[10];
            int nSix = 0;
            int nThree = 0;
            int nAll = 0;
            for (int i = nIndex + lenght - 1; i >= nIndex; i--)
            {
                // 获取彩票
                Lottery lottery = m_lotterys[i];
                param[Convert.ToInt32(lottery.Code[2].ToString())]++;
                param[Convert.ToInt32(lottery.Code[3].ToString())]++;
                param[Convert.ToInt32(lottery.Code[4].ToString())]++;
            }

            return param;
        }

        /// <summary>
        /// 计算数字当前窗口个数到下个窗口个数2阶矩阵
        /// </summary>
        /// <param name="nNo">指定数字的标号</param>
        /// <param name="nCount">窗口个数</param>
        /// <returns></returns>
        public int[,] CalulateNumMatrix(int nNo, int nCount = 20)
        {
            int[,] CombinMatrix = new int[nCount + 1, nCount + 1];                 // 转移矩阵
            for (int i = 0; i < nCount + 1; i++)
            {
                for (int j = 0; j < nCount + 1; j++)
                {
                    for (int k = 20000; k > nCount; k--)
                    {
                        int[] param = GetNumCount(k, nCount);
                        int[] nextParam = GetNumCount(k - nCount, nCount);
                        int nSix = param[nNo];
                        int nNext = nextParam[nNo];

                        if (nSix == i && nNext == j)
                        {
                            CombinMatrix[i, j]++;
                        }
                    }
                }

            }

            return CombinMatrix;
        }


        /// <summary>
        /// 计算数字当前窗口个数到下个窗口个数3阶矩阵
        /// </summary>
        /// <param name="nNo">指定数字的标号</param>
        /// <param name="nCount">窗口个数</param>
        /// <returns></returns>
        public int[, ,] CalulateNumMatrix3(int nNo, int nCount = 20)
        {
            int[, ,] CombinMatrix = new int[nCount + 1, nCount + 1, nCount + 1];                 // 转移矩阵
            for (int i = 0; i < nCount + 1; i++)
            {
                for (int j = 0; j < nCount + 1; j++)
                {
                    for (int n = 0; n < nCount + 1; n++)
                    {
                        for (int k = 20000; k > 2 * nCount; k--)
                        {
                            int[] param = GetNumCount(k, nCount);
                            int[] nextParam = GetNumCount(k - nCount, nCount);
                            int[] next2Param = GetNumCount(k - nCount * 2, nCount);
                            int nSix = param[nNo];
                            int nNext = nextParam[nNo];
                            int n2Next = next2Param[nNo];

                            if (nSix == i && nNext == j && n2Next == n)
                            {
                                CombinMatrix[i, j, n]++;
                            }
                        }
                    }
                }

            }

            return CombinMatrix;
        }

        /// <summary>
        /// 计算连续相同数字到下个不相等数字的转移举证
        /// </summary>
        /// <param name="nNo"></param>
        /// <returns></returns>
        public int[,] CalulateContinueToUnMatrix(int nNo)
        {
            int[,] CombinMatrix = new int[10, 40];                 // 转移矩阵
            bool bIsContinueSame = false;
            int nContiuneSameCount = 0;
            int nContiuneUnSameCount = 0;
            for (int k = 20000; k > 0; k--)
            {
                if (GetNumCount(k, 1)[nNo] >= 1)
                {
                    if (!bIsContinueSame)              // 上一次不是相同数字
                    {
                        CombinMatrix[nContiuneUnSameCount, nContiuneSameCount]++;
                        nContiuneSameCount = 0;
                        nContiuneUnSameCount = 0;
                    }
                    bIsContinueSame = true;
                    nContiuneUnSameCount++;
                }
                else
                {
                    bIsContinueSame = false;
                    nContiuneSameCount++;
                }
            }

            return CombinMatrix;
        }
#endregion

        #region 获取类型
        public static ThreeDistribution GetThreDis(double dPercent)
        {
            ThreeDistribution dis = ThreeDistribution.EN_THREEDIS_BAD;
            if (dPercent <= 0.15)
            {
                dis = ThreeDistribution.EN_THREEDIS_GOOD;
            }
            else if (dPercent <= 0.25)
            {
                dis = ThreeDistribution.EN_THREEDIS_LITTLE_GOOD;
            }
            else if (dPercent <= 0.4)
            {
                dis = ThreeDistribution.EN_THREEDIS_NORMAL;
            }
            else if (dPercent <= 0.5)
            {
                dis = ThreeDistribution.EN_THREEDIS_LITTLE_NORMAL;
            }
            else if (dPercent <= 0.75)
            {
                dis = ThreeDistribution.EN_THREEDIS_LITTLE_BAD;
            }
            else if (dPercent <= 1)
            {
                dis = ThreeDistribution.EN_THREEDIS_BAD;
            }
            else
            {
                dis = ThreeDistribution.EN_THREEDIS_BAD;
            }

            return dis;
        }
        #endregion

#region 通用计算方法

        /// <summary>
        /// 计算置信区间
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="percent"></param>
        /// <returns></returns>
        public static int[] GetBestRange(int[] arr, double percent)
        {
            int[] result = null;
            // 先计算总和
            double nTotal = 0;
            for (int i = 0; i < arr.GetLength(0); i++)
            {
                nTotal += arr[i];
            }

            // 求置信区间
            for (int i = 0; i < arr.GetLength(0); i++)
            {
                double tempTotal = 0;
                for (int j = i; j < arr.GetLength(0); j++)
                {
                    tempTotal += arr[j];

                    // 判断是否满足要求
                    if (tempTotal / nTotal >= percent)
                    {
                        result = new int[2];
                        result[0] = i;
                        result[1] = j;
                        return result;
                    }
                }
            }

            return result;
        }

        // 从小到大排序后的数字
        public int[] Sort(int[] PerCount)
        {
            List<int> list = PerCount.ToList();
            int[] sortResult = new int[10];

            // 加入到一个结构体中
            List<Uint> temps = new List<Uint>();
            for (int i = 0; i < PerCount.Length; i++)
            {
                Uint temp = new Uint();
                temp.nNo = i;
                temp.value = PerCount[i];
                temps.Add(temp);
            }

            // 冒泡排序
            for (int i = temps.Count; i > 0; i--)
            {
                for (int j = 0; j < i - 1; j++)
                {
                    if (temps[j].value > temps[j + 1].value)
                    {
                        Uint temp = temps[j];
                        temps[j] = temps[j + 1];
                        temps[j + 1] = temp;
                    }
                }
            }

            // 放到结果中去
            for (int i = 0; i < temps.Count; i++)
            {
                sortResult[i] = temps[i].nNo;
            }

            // 返回
            return sortResult;
        }

        private class Uint
        {
            public int nNo;
            public int value;
        }
#endregion
    }
}
